/*--------------------------------------------------------------------------------------------------
Yatak Operation System Project Copyright 2012-2013
Author : Ilya Churaev
Started : 17 Jun 2012		Updated : 18 Nov 2012
File Name : kheap.h			Purpose : Interface for kernel heap functionsm.
--------------------------------------------------------------------------------------------------*/
#ifndef _KHEAP_H
#define _KHEAP_H

#ifdef __cplusplus
extern "C" {
#endif

#include <types.h>
#include <ordered_array.h>

#define KHEAP_START			0x20000000
//#define KHEAP_START			0x50000000
#define KHEAP_INITIAL_SIZE	0x1000000
#define KHEAP_MAX_ADDRESS	0xFFFF000

#define HEAP_INDEX_SIZE   0x20000
#define HEAP_MAGIC        0x123890AB
#define HEAP_MIN_SIZE     0x70000

// Информация о размере неиспользуемого фрагмента/используемого блока памяти
typedef struct
{
	uint32 magic;					// Магическое число, для контроля ошибок и индентификации
	uint8 is_hole;					// 1 - если это неиспользуемый фрагмент памяти, 0 - если используемый блок
	uint32 size;					// Размер блока, в том числе завершающая запись блога.
} header_t;

typedef struct
{
	uint32 magic;					// То же самое, что и в header_t
	header_t * header;				// Указатель на заголовок блока
} footer_t;

typedef struct
{
	ordered_array_t index;
	uint32 start_address;			// Начало выделяемого пространства памяти
	uint32 end_address;				// Конец выделяемого пространства памяти, может быть до значения max_address
	uint32 max_address;				// Максимальный адрес, до которого куча может расширяться.
	uint8 supervisor;				// Должны ли дополнительные страницы использоваться только в режиме супервизора
	uint8 readonly;					// Должны ли дополнительные страницы использоваться только для чтения
} heap_t;

// Создаем новую кучу
heap_t *create_heap(uint32 start, uint32 end, uint32 max, uint8 supervisor, uint8 readonly);

// Allocates a contiguous region of memory 'size' in size. If page_align==1, it creates that block starting
// on a page boundary.
void *alloc(uint32 size, uint8 page_align, heap_t *heap);

//Releases a block allocated with 'alloc'.
void free(void *p, heap_t *heap);

/*
   Allocate a chunk of memory, sz in size. If align == 1,
   the chunk must be page-aligned. If phys != 0, the physical
   location of the allocated chunk will be stored into phys.

   This is the internal version of kmalloc. More user-friendly
   parameter representations are available in kmalloc, kmalloc_a,
   kmalloc_ap, kmalloc_p.
*/
uint32 kmalloc_int(uint32 sz, int align, uint32 *phys);

// Allocate a chunk of memory, sz in size. The chunk must be
// page aligned.
uint32 kmalloc_a(uint32 sz);

// Allocate a chunk of memory, sz in size. The physical address
// is returned in phys. Phys MUST be a valid pointer to uint32!
uint32 kmalloc_p(uint32 sz, uint32 *phys);

// Allocate a chunk of memory, sz in size. The physical address 
// is returned in phys. It must be page-aligned.
uint32 kmalloc_ap(uint32 sz, uint32 *phys);

// General allocation function.
uint32 kmalloc(uint32 sz);

// General deallocation function.
int kfree(void *p);

// Return amount of memory used
uint32 get_memory_usage();

// Expand and contract heap
void expand(uint32 new_size, heap_t *heap);
uint32 contract(uint32 new_size, heap_t *heap);

#ifdef __cplusplus
}
#endif

#endif
